#pragma once
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include <unordered_map>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <array>
#include <any>
#include <cassert>
#include <ctime>
#include <cstring>
#include <cstdarg>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/timerfd.h>


// 实现一个用于输出信息的日志类
const int mesgSize = 1024;
const std::string logFile = "./log/log.txt";

enum recordOption
{
    screen,
    oneFile,
    diverseFile
};

enum Level
{
    Info,
    Debug,
    Warning,
    Error,
    Fatal
};

class Log
{
public:
    // 使用指定方法记录日志
    void changeRecordOp(recordOption op) { _op = op; }
    void startUpLevel(Level l) { _lowLevel = l; }
    void operator()(Level l, const char* format, ...)
    {
        if (l < _lowLevel) return;
        char rightBuffer[mesgSize], leftBuffer[mesgSize];
        va_list parameter;
        va_start(parameter, format);
        vsnprintf(rightBuffer, mesgSize, format, parameter);
        time_t nowTime = 0;
        time(&nowTime);
        struct tm* timeSt = localtime(&nowTime);
        snprintf(leftBuffer, mesgSize, "[%p - %s] [%d-%d-%d %d:%d:%d] @ ", (void*)pthread_self(), levelToString(l).c_str(), timeSt->tm_year + 1900, timeSt->tm_mon + 1, timeSt->tm_mday, timeSt->tm_hour, timeSt->tm_min, timeSt->tm_sec);
        std::string mesg;
        mesg += leftBuffer;
        mesg += rightBuffer;
        mesg += '\n';
        recordLog(l, mesg);
    }

private:
    // 日志输出方式
    recordOption _op = screen;
    bool _lowLevel = Info;
    // 写入文件中
    void writeToFile(Level l, const std::string& mesg, const std::string& file_name)
    {
        int fd = open(file_name.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (fd < 0)
        {
            perror("open");
            exit(1);
        }
        write(fd, mesg.c_str(), mesg.size());
        close(fd);
    }
    // 发送日志
    void recordLog(Level l, const std::string& mesg)
    {
        if (_op == screen)
            std::cout << mesg;
        else if (_op == oneFile)
            // 都是进行文件写入的操作
            writeToFile(l, mesg, logFile);
        else
            writeToFile(l, mesg, logFile + "." + levelToString(l));
    }
    // 将等级转换成string
    const std::string levelToString(Level l)
    {
        switch (l)
        {
        case Info:
            return "Info";
            break;
        case Debug:
            return "Debug";
            break;
        case Warning:
            return "Warning";
            break;
        case Error:
            return "Error";
            break;
        case Fatal:
            return "Fatal";
            break;
        default:
            return "None";
            break;
        }
    }
};

Log lg;

// 实现一个buffer类作为通用缓冲区
class Buffer
{
    static constexpr size_t defaultCapacity = 1024;

private:
    std::vector<char> _container;
    size_t _readerIdx = 0;
    size_t _writerIdx = 0;

public:
    Buffer(const size_t capacity = defaultCapacity) : _container(capacity) {}

private:
    // 获取末尾剩余空间
    size_t getTailCapacity() { return _container.size() - _writerIdx; }
    // 获取头部的剩余空间
    size_t getHeadCapacity() { return _readerIdx; }

    // 使缓冲区满足需求
    void satisfyCapcity(size_t capcacity)
    {
        if (_container.size() - _writerIdx >= capcacity)
            return;
        if (getTailCapacity() + getHeadCapacity() >= capcacity)
        {
            // 如果满足，需要将数据前移并进行扩容
            size_t cap = getReadAbleSize();
            std::copy(getReadPos(), getWritePos(), _container.begin());
            _readerIdx = 0, _writerIdx = cap;
        }
        else
        {
            // 如果所有空间都不够，就需要扩容了
            long long newCapcity = (_writerIdx + capcacity) * 1.5;
            // 如果扩容后的空间已经超过size_t范围，直接报错
            assert(newCapcity <= SIZE_MAX);
            size_t nextCapcity = (_writerIdx + capcacity) * 1.5;
            _container.resize(nextCapcity);
        }
    }
public:
    // 可读指针后移
    void readerIdxGo(size_t len)
    {
        assert(_readerIdx + len <= _writerIdx);
        _readerIdx += len;
    }
    // 后移写位置
    void writerIdxGo(size_t len)
    {
        assert(_writerIdx + len <= _container.size());
        _writerIdx += len;
    }
    /*获取读写位置*/
    char* getReadPos() { return &_container[_readerIdx]; }
    char* getWritePos() { return &_container[_writerIdx]; }

public: /*从缓冲区读取数据*/
    // 获取当前可读空间大小
    size_t getReadAbleSize() const { return _writerIdx - _readerIdx; }
    // 将数据读入用户的数组内部
    bool read(void* data, size_t len, bool needPop = true)
    {
        // 把数据传入data中，使用copy进行拷贝

        if (len > getReadAbleSize())
        {
            lg(Warning, "There is not enough data in the buffer, buffer readAble size: %ld", getReadAbleSize());
            return false;
        }
        std::copy(getReadPos(), getReadPos() + len, static_cast<char*>(data));
        if (needPop)
            readerIdxGo(len);
        return true;
    }
    // 重载read读入string中
    std::string read(size_t len, bool needPop = true)
    {
        std::string ret;
        ret.resize(len);
        if (!read(&ret[0], len, needPop))
            return "";
        return ret;
    }
    // 读取一行数据，专门为http协议支持
    std::string getline(bool needPop = true)
    {
        char* pos = std::find(getReadPos(), getWritePos(), '\n');
        if (pos == getWritePos())
            return "";
        std::string ret = read(pos - getReadPos() + 1, needPop);
        return ret;
    }

public: /*写入数据的相关API*/
    // 各参数同read
    bool write(const void* data, size_t len, bool needPush = true)
    {
        // 把数据写入缓冲区中
        satisfyCapcity(len);
        std::copy(static_cast<const char*>(data), static_cast<const char*>(data) + len, getWritePos());
        if (needPush)
            writerIdxGo(len);
        return true;
    }
    bool write(const std::string& data, bool needPush = true) { return write(&data[0], data.size(), needPush); }
    bool write(const Buffer& buf) { return write(&buf._container[buf._readerIdx], buf.getReadAbleSize(), true); }

public: // 清空缓冲区
    void clear() { _readerIdx = _writerIdx = 0; }
    bool empty() { return _readerIdx == _writerIdx; }
};

// 对socket进行封装
enum TcpError
{
    CreateError = 1,
    BindError,
    ListenError
};

const size_t ipSize = 30;
const int defaultBacklog = 10;

class tcpSocket
{
public:
    tcpSocket(const int fd = -1)
        : _sockfd(fd) {}
    ~tcpSocket() { close(); }

public:
    void create()
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            perror("create socket");
            // lg(Fatal, "create sockfd error, errno:%d, strerr:%s", errno, strerror(errno));
            exit(CreateError);
        }
        lg(Info, "create a sockfd, fd: %d", _sockfd);
    }

    int setReuseAddr()
    {
        int opt = 1;
        return setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof opt);
    }

    // 将当前套接字绑定到端口和ip
    int bind(const uint16_t port, const std::string& ip = "0.0.0.0")
    {
        struct sockaddr_in info;
        memset(&info, 0, sizeof info);
        info.sin_family = AF_INET;
        // info.sin_addr.s_addr = INADDR_ANY;
        info.sin_addr.s_addr = inet_addr(ip.c_str());
        info.sin_port = htons(port);
        socklen_t len = sizeof info;
        return ::bind(_sockfd, (const sockaddr*)&info, len);
    }

    // 返回一个表示连接的套接字, 并且使用输出型参数返回请求方的ip和端口号
    int accept(std::string* src_ip, uint16_t* src_port)
    {
        struct sockaddr_in src;
        socklen_t len = sizeof src;
        int fd = ::accept(_sockfd, (sockaddr*)&src, &len);
        if (fd < 0)
            return fd;
        // lg(Info, "server get a link, fd: %d", fd);
        char ip[ipSize] = { 0 };
        *src_ip = inet_ntop(AF_INET, &(src.sin_addr), ip, sizeof ip);
        *src_port = ntohs(src.sin_port);
        return fd;
    }

    int accept()
    {
        struct sockaddr_in src;
        socklen_t len = sizeof src;
        int fd = ::accept(_sockfd, (sockaddr*)&src, &len);
        if (fd < 0)
        {
            lg(Warning, "accept error, errno:%d, str:%s", errno, strerror(errno));
            return fd;
        }
        lg(Info, "server get a link, fd: %d", fd);
        return fd;
    }

    // 让当前套接字开启监听状态，等待连接
    int listen(int backlog = defaultBacklog) { return ::listen(_sockfd, backlog); }

    bool connect(const std::string& dst_ip, const uint16_t src_port)
    {
        struct sockaddr_in dst;
        memset(&dst, 0, sizeof dst);
        dst.sin_family = AF_INET;
        dst.sin_addr.s_addr = inet_addr(dst_ip.c_str());
        dst.sin_port = htons(src_port);
        socklen_t len = sizeof dst;
        int n = ::connect(_sockfd, (const sockaddr*)&dst, len);
        if (n < 0)
        {
            lg(Error, "Connection to server failed, server ip:%s, port:%hd", dst_ip.c_str(), src_port);
            return false;
        }
        return true;
    }

    bool close()
    {
        if (_sockfd >= 0)
        {
            ::close(_sockfd);
            lg(Info, "sock:%d close the link", _sockfd);
            _sockfd = -1;
        }
        return true;
    }

    int fd() { return _sockfd; }

    void setNoBlock()
    {
        int flags = fcntl(_sockfd, F_GETFL);
        fcntl(_sockfd, F_SETFL, flags | O_NONBLOCK);
    }

public:
    /*关于网络通信的读写相关接口*/
    // 如果返回-1, 也有可能是由于阻塞状态导致的, 直接返回-1， 如果是其他错误，那就需要打印日志
    //
    ssize_t recv(void* data, size_t len, bool noBlock)
    {
        int flag = 0;
        if (noBlock)
            flag = MSG_DONTWAIT;
        ssize_t n = ::recv(_sockfd, data, len, flag);
        if (n == -1)
        {
            if (errno == EWOULDBLOCK || errno == EINTR)
                return n;
            else
                lg(Warning, "read error, errno:%d, str:%s", errno, strerror(errno));
        }
        return n;
    }
    ssize_t recv(std::string* str, size_t len, bool noBlock)
    {
        std::vector<char> v(len + 1);
        ssize_t n = recv(v.data(), len, noBlock);
        if (n == -1)
            return n;
        *str = v.data();
        return n;
    }
    ssize_t send(const void* data, size_t len, bool noBlock)
    {
        int flag = 0;
        if (noBlock)
            flag = MSG_DONTWAIT;
        ssize_t n = ::send(_sockfd, data, len, flag);
        if (n == -1)
        {
            if (errno == EWOULDBLOCK || errno == EINTR)
                return n;
            else
                lg(Warning, "read error, errno:%d, str:%s", errno, strerror(errno));
        }
        return n;
    }
    ssize_t send(const std::string str, bool noBlock)
    {
        return send(str.c_str(), str.size(), noBlock);
    }

public:   /*组合封装接口，便于快速使用*/
    bool createServer(const uint16_t port, bool noBlock = true, const std::string& ip = "0.0.0.0")
    {
        // 创建套接字
        create();
        // 设置套接字成非阻塞状态
        if (noBlock)
            setNoBlock();
        // 设置端口复用
        if (setReuseAddr() == -1)
        {
            lg(Warning, "set reuseAddr error, errno:%d, str:%s", errno, strerror(errno));
            return false;
        }
        // 绑定端口号
        if (bind(port, ip) == -1)
        {
            lg(Warning, "bind error, errno:%d, str:%s", errno, strerror(errno));
            return false;
        }
        // 开启监听状态
        if (listen() == -1)
        {
            lg(Warning, "set listen error, errno:%d, str:%s", errno, strerror(errno));
            return false;
        }
        return true;
    }

    bool createClient(const std::string& ip, const uint16_t port)
    {
        create();
        if (connect(ip, port) == -1)
        {
            lg(Warning, "connect error, errno:%d, str:%s", errno, strerror(errno));
            return false;
        }
        return true;
    }

private:
    int _sockfd;
};

class eventLoop;
// 用于文件描述符的事件管理
class channel
{
    using EventCallBk = std::function<void()>;

private:
    int _fd;
    uint32_t _events = 0;
    uint32_t _revents = 0;
    eventLoop* _loop;

private:
    EventCallBk _readCb;
    EventCallBk _writeCb;
    EventCallBk _closeCb;
    EventCallBk _allCb;
    EventCallBk _errCb;

public: /*各个属性的get和set*/
    // 每个channel都需要绑定一个特定的事件循环
    channel(eventLoop* loop, const int fd = -1) : _fd(fd), _loop(loop) {}
    ~channel()
    {
        // 目前为止， 一个fd和一个channel关联，如果channel析构，fd也要同时关闭
        // channel不需要进行关闭操作，整体关闭操作通过tcpSocket模块进行，这里进行关闭操作是为了测试
        // if (_fd >= 0)
        // {
        //     close(_fd);
        //     lg(Info, "channel delete, fd close too, fd:%d", _fd);
        // }
    }
    int fd() const { return _fd; }
    /*对于事件和当前需处理事件的设置*/
    uint32_t getEvent() { return _events; }
    void setRevent(const uint32_t events) { _revents = events; }
    /*设置各种事件发生时的回调函数*/
    void setReadCb(const EventCallBk& bk) { _readCb = bk; }
    void setWriteCb(const EventCallBk& bk) { _writeCb = bk; }
    void setCloseCb(const EventCallBk& bk) { _closeCb = bk; }
    void setAllCb(const EventCallBk& bk) { _allCb = bk; }
    void setErrCb(const EventCallBk& bk) { _errCb = bk; }

public: /*设置需要监控的事件并更新至eventloop以及查询是否查否事件*/
    bool isMonitorRead() { return _events & EPOLLIN; }
    bool isMonitorWrite() { return _events & EPOLLOUT; }
    // 设置该channel读事件监控
    void setMonitorRead()
    {
        _events |= EPOLLIN;
        update();
    }
    // 设置写事件监控
    void setMonitorWrite()
    {
        _events |= EPOLLOUT;
        update();
    }
    void delMonitorRead()
    {
        _events &= ~EPOLLIN;
        update();
    }
    void delMonitorWrite()
    {
        _events &= ~EPOLLOUT;
        update();
    }
    void delMonitorAll()
    {
        _events = 0;
        update();
    }
    // 从eventloop中取消管理该channel
    void revChannel() { remove(); }

private:
    void update();
    void remove();

public: /*事件处理*/
    void handleEvent()
    {

        if (_allCb)
            _allCb();
        // 将错误事件和关闭连接事件都转换成写事件，在写事件内部处理
        if (_revents & EPOLLERR)
        {
            if (_errCb)
                _errCb();
            _revents |= EPOLLIN;
        }
        if (_revents & EPOLLHUP)
        {
            if (_closeCb)
                _closeCb();
            _revents |= EPOLLIN;
        }
        if (_revents & EPOLLOUT)
            if (_writeCb)
                _writeCb();
        if ((_revents & EPOLLIN) || (_revents & EPOLLPRI) || (_revents & EPOLLRDHUP))
            if (_readCb)
                _readCb();
        _revents = 0;
    }
};

/*epollerI/O多路复用模块*/
class epoller
{
    static constexpr int maxEvents = 1024;

public:
    epoller()
    {
        _epfd = epoll_create(128);
        if (_epfd == -1)
        {
            lg(Error, "epoller creat fail, errno:%d, errstr:%s", errno, strerror(errno));
            exit(2);
        }
        lg(Info, "create a epoll fd, fd: %d", _epfd);
    }

    ~epoller()
    {
        if (_epfd >= 0)
            close(_epfd);
    }

private:
    int epollUpdateHelper(const int op, const int fd, const uint32_t events)
    {
        struct epoll_event newEvent;
        newEvent.data.fd = fd;
        newEvent.events = events;
        return epoll_ctl(_epfd, op, fd, &newEvent);
    }
    bool isInMonitorFd(int fd) { return _channels.count(fd); }

public: /*对于epoll中fd的增删查改*/
    int epollFileDel(const channel* model)
    {
        int fd = model->fd();
        if (!isInMonitorFd(fd))
        {
            lg(Warning, "this delete fd is not in epoller, fd:%d", fd);
            return -1;
        }
        // 删除关心的连接
        _channels.erase(fd);
        return epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
    }

    int epollUpdate(channel* model, const uint32_t events)
    {
        int fd = model->fd();
        if (isInMonitorFd(fd))
            return epollUpdateHelper(EPOLL_CTL_MOD, fd, events);
        else
        {
            // 如果是第一次创建，打印日志信息,将其添加到哈希表中记录起来，并且将其加入epoll监控中
            _channels[fd] = model;
            int n = epollUpdateHelper(EPOLL_CTL_ADD, fd, events);
            if (n >= 0) lg(Info, "add a new monitor file, fd:%d", fd);
            return n;
        }
    }

    int getReadyEvent(std::vector<channel*>* channels, int timeout = -1)
    {
        int n = epoll_wait(_epfd, _events, maxEvents, timeout);
        if (n > 0)
        {
            // lg(Info, "epoller get %d events", n);
            // 将event传出channels
            for (int i = 0; i < n; ++i)
            {
                int fd = _events[i].data.fd;
                if (!isInMonitorFd(fd))
                {
                    lg(Debug, "the ready file don't in map, the process maybe error!, fd:%d", fd);
                    return -1;
                }
                _channels[fd]->setRevent(_events[i].events);
                channels->push_back(_channels[fd]);
            }
        }
        else if (n == 0)
            lg(Info, "epoll wait timeout!");
        else
            lg(Error, "epoll wait error, errno:%d, \"%s\"", errno, strerror(errno));
        return n;
    }

private:
    int _epfd;
    std::unordered_map<int, channel*> _channels;
    struct epoll_event _events[maxEvents];
};

/*时间轮模块*/
using timerFunc = std::function<void()>;
using delFunc = std::function<void()>;

/*定时事件模块*/
class TimerTask
{
private:
    uint64_t _id;            // 定时任务ID
    size_t _timeOut;         // 到期时间
    timerFunc _FuncCb;       // 定时任务
    delFunc _deleCb;         // 删除时间轮中的任务
    bool _isCancel;
public:
    TimerTask(const uint64_t id, const size_t timeout, const timerFunc& funcCb)
        :_id(id), _timeOut(timeout), _FuncCb(funcCb), _isCancel(false) {}
    void setDelFunc(const delFunc& delCb) { _deleCb = delCb; }
    size_t getDelayTime() { return _timeOut; }
    void cancelTask() { _isCancel = true; }
    // 当对象析构时执行定时任务
    ~TimerTask()
    {
        if (!_isCancel)
        {
            _FuncCb();
            if (_deleCb) _deleCb();
            lg(Info, "the timer task is execute, id: %ld", _id);
        }
    }   // 只有没有删除，才需要执行任务 }  // 析构时进行任务
};

/*时间轮模块*/
class TimeWheel      // 只有当所有shared_ptr全部被释放才会执行任务
{
    using ptrTask = std::shared_ptr<TimerTask>;
    using ptrWeak = std::weak_ptr<TimerTask>;
private:
    std::vector<std::vector<ptrTask>> _wheel;
    std::unordered_map<uint64_t, ptrWeak> _idMap;    // 存储每个id对应任务的weak_ptr, 便于通过其构造出共享引用计数的shared_ptr
    size_t _tick;                                    // 当前指针指向的位置
    std::shared_ptr<channel> _timerfdChannel;        // 这里存储的是有关定时器的事件管理模块
    eventLoop* _loop;                                // 用于对timerfd事件管理的绑定
    size_t _maxOutTime;
public:
    TimeWheel(eventLoop* loop, size_t maxOutTime) :_tick(0), _loop(loop), _maxOutTime(maxOutTime) {}
    TimeWheel(size_t maxOutTime) : _tick(0), _maxOutTime(maxOutTime), _loop(nullptr) {}

    void init()
    {
        // 创建timerfd的channel事件管理模块
        _wheel.resize(_maxOutTime);
        createTimerChannel();
        _timerfdChannel->setReadCb([this] { this->overTimeHanler(); });
        _timerfdChannel->setMonitorRead();
    }

private:   // timerfd相关操作
    void createTimerChannel()
    {
        int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
        if (timerfd < 0)
        {
            lg(Error, "timerfd create false, errno:%d, \"%s\"", errno, strerror(errno));
            abort();
        }
        lg(Info, "create a timerfd, fd: %d", timerfd);
        struct itimerspec timesp;
        memset(&timesp, 0, sizeof timesp);
        // 设置第一次提醒的时间
        timesp.it_value.tv_sec = 1;
        // 设置之后每一次提醒的时间
        timesp.it_interval.tv_sec = 1;
        timerfd_settime(timerfd, 0, &timesp, nullptr);
        _timerfdChannel = std::make_shared<channel>(_loop, timerfd);
    }

private:
    void removeTask(const uint64_t id)
    {
        if (!_idMap.count(id))
        {
            lg(Warning, "this id %ld can't find in timeWheel", id);
            return;
        }
        _idMap.erase(id);
        lg(Info, "remove %ld timer task success", id);
    }

public:       /* 定时事件的增加，延时和删除, 单独使用时间轮时提供的接口 */
    bool addTimerTask(const uint64_t id, const size_t timeout, const timerFunc& funcCb)
    {
        if (_idMap.count(id))
        {
            lg(Warning, "this timeWheel already have %d task", id);
            return false;
        }
        auto newTask = std::make_shared<TimerTask>(id, timeout, funcCb);
        // 还需要为当前任务设置删除哈希的del函数，否则会导致内存泄漏
        newTask->setDelFunc([this, id] { this->removeTask(id); });
        size_t pos = (_tick + timeout - 1) % _maxOutTime;
        _wheel[pos].push_back(newTask);    // 在将要执行的位置添加任务
        _idMap[id] = newTask;
        return true;
    }

    bool delayTimerTask(const uint64_t id)
    {
        if (!_idMap.count(id))
        {
            lg(Warning, "this id %ld can't find in timeWheel", id);
            return false;
        }
        auto ptrToTask = _idMap[id].lock();
        size_t outTime = ptrToTask->getDelayTime();
        size_t pos = (_tick + outTime) % _maxOutTime;
        _wheel[pos].push_back(std::move(ptrToTask));
        return true;
    }

    bool cancelTimerTask(const uint64_t id)
    {  // 如果取消之后时间轮中还有取消的任务，那么无法添加相同id的任务
        if (!_idMap.count(id))
        {
            lg(Warning, "this timewheel don't have id: %ld task", id);
            return false;
        }
        // 这里有可能已经在执行任务了，所以析构函数已经执行，对象已经不存在了
        if (_idMap[id].expired())
        {
            // lg(Warning, "cancel error, this id %ld already expired", id);
            return false;
        }
        auto ptrToTask = _idMap[id].lock();
        ptrToTask->cancelTask();
        ptrToTask.reset();   // 手动删除
        _idMap.erase(id);
        lg(Info, "the id: %ld timer task is cancel", id);
        return true;
    }

public:      // 上面提供的接口在单独使用的时候会有线程安全的问题，需要用户外部加锁
    // 提供下面接口确保任务在eventLoop模块中使用，确保任务在一个线程中执行，不需要加锁

/*由于下面的接口需要调用eventLoop模块的接口，所以将其定义放在eventLoop模块之后*/
    bool addTimer(const uint64_t id, const size_t timeout, const timerFunc& funcCb);
    bool delayTimer(const uint64_t id);
    bool cancelTimer(const uint64_t id);
public:    // 事件的运行处理相关函数
    void wheelRun()
    {
        _wheel[_tick].clear();  // 将走过的位置里所有的shared_ptr清空
        _tick = (_tick + 1) % _maxOutTime;
    }
    // 超时事件处理
    void overTimeHanler()
    {
        uint64_t num = 0;
        int timerfd = _timerfdChannel->fd();
        ssize_t n = read(timerfd, &num, 8);
        if (n < 0)
        {
            lg(Error, "read timerfd error, errno:%d, \"%s\"", errno, strerror(errno));
            abort();
        }
        // lg(Debug, "timerfd over %d times", num);
        // 通过read读取到超时时间， 然后根据超时时间运行实践论
        while (num--)
            wheelRun();
    }

    // 检查当前是否存在这个任务
    /* 这个接口存在线程安全问题， 单独使用时用户需要自行加锁*/
    bool hasTimer(const uint64_t id) { return _idMap.count(id); }

};

/*时间循环模块*/
static constexpr size_t defaultMaxTimeOut = 60;
using functor = std::function<void()>;
class eventLoop
{
private:
    epoller _epoller;                         // 每个eventLoop对应一个epoller
    std::vector<functor> _taskPoll;           // 任务队列，用来存放用户在其他线程中产生的任务
    std::thread::id _thisId;                  // eventLoop所在线程的Id
    std::mutex _mtx;                          // 用于防止外界的多线程访问造成的线程安全问题
    std::shared_ptr<channel> _eventChannel;   // eventfd用于对事件通知进行处理
    TimeWheel _timeWheel;                     // 时间轮：用于对超时时间进行处理

public:          // 构造，析构以及初始化函数
    eventLoop(const size_t maxTimeOut = defaultMaxTimeOut) : _thisId(std::this_thread::get_id()), _timeWheel(this, maxTimeOut) {}

    ~eventLoop() = default;

    void init()
    {
        _timeWheel.init();
        createEventFd();
        _eventChannel->setReadCb([this] {this->readEventfd();});
        _eventChannel->setMonitorRead();   // 设置可读事件监控
    }

public:          /*eventfd相关API*/
    void createEventFd()
    {
        int eventFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (eventFd < 0)
        {
            lg(Fatal, "eventfd create error, errno:%d, \"%s\"", errno, strerror(errno));
            abort();
        }
        lg(Info, "create a eventfd, fd: %d", eventFd);
        _eventChannel = std::make_shared<channel>(this, eventFd);
    }

    void readEventfd()
    {
        uint64_t ret = 0;
        int fd = _eventChannel->fd();
        while (true)
        {
            ssize_t n = read(fd, &ret, sizeof ret);
            if (n < 0)
            {
                // 如果是因为非阻塞/信号中断导致的返回-1，就属于正常终端，不用abort()
                if (errno == EINTR || errno == EWOULDBLOCK) break;
                else
                {
                    lg(Error, "eventfd read error, errno:%d, errstr:%s", errno, strerror(errno));
                    abort();
                }
            }
        }
    }

    void wakeUpLoop()
    {
        uint64_t sig = 1;
        int fd = _eventChannel->fd();
        ssize_t n = write(fd, &sig, sizeof sig);
        if (n < 0)
        {
            lg(Error, "write to event fd error, errno:%d, \"%s\"", errno, strerror(errno));
            abort();
        }
    }

    /* 关于任务的执行和添加相关的操作 */
private:
    void pushToPoll(const functor& func)
    {
        std::unique_lock<std::mutex> guide(_mtx);
        _taskPoll.push_back(std::move(func));
    }
public:
    // 执行当前任务池中所有任务
    void runAllTask()
    {
        // 由于这一操作一定只能在一个线程中访问，所以需要枷锁
        std::vector<functor> readyTask;
        {
            std::unique_lock<std::mutex> guide(_mtx);
            _taskPoll.swap(readyTask);
        }
        for (auto& task : readyTask)
            task();
    }
    bool isInLoop() { return std::this_thread::get_id() == _thisId; }
    void assertInLoop() { assert(std::this_thread::get_id() == _thisId); }
    // 添加任务到loop中 
    void PushTask(const functor& func)
    {
        if (isInLoop())
            func();
        else
            pushToPoll(func);
        // 添加之后，为了防止epoller长时间阻塞，需要唤醒eventfd
        wakeUpLoop();
    }
    // 不进行检验，直接推入任务队列
    void pushTaskToPoll(const functor& func) {
        pushToPoll(func);
        wakeUpLoop();
    }

public:    // 执行逻辑
    void start(int timeout = -1)
    {
        while (true)
        {
            std::vector<channel*> readyEvents;
            // 1. 获取当前已经就绪的事件类channel
            _epoller.getReadyEvent(&readyEvents, timeout);
            // 2. 逐个处理事件
            for (const auto event : readyEvents)
            {
                // lg(Debug, "handle event fd, fd: %d", event->fd());
                event->handleEvent();
            }
            // 3. 处理任务池中的事件
            runAllTask();
        }
    }

public:        /*关于事件监控的管理接口*/
    void setFdMonitor(channel* ch, uint32_t events) { _epoller.epollUpdate(ch, events); }

    void delFdMonitor(channel* ch) { _epoller.epollFileDel(ch); }

public:        /*关于时间轮相关的操作*/
    void addTimer(const uint64_t id, const size_t timeout, const timerFunc& funcCb) { _timeWheel.addTimer(id, timeout, funcCb); }

    void delayTimer(const uint64_t id) { _timeWheel.delayTimer(id); }

    void cancelTimer(const uint64_t id) { _timeWheel.cancelTimer(id); }

    bool hasTimer(const uint64_t id) { return _timeWheel.hasTimer(id); }
};

//////////////////////////////

void channel::update() { _loop->setFdMonitor(this, _events); }

void channel::remove() { _loop->delFdMonitor(this); }

//////////////////////////////

bool TimeWheel::addTimer(const uint64_t id, const size_t timeout, const timerFunc& funcCb) {
    if (!_loop)
    {
        lg(Warning, "loop is unllptr, can't call addTimer");
        return false;
    }
    _loop->PushTask([this, id, timeout, &funcCb] { this->addTimerTask(id, timeout, funcCb); });
    return true;
}

bool TimeWheel::delayTimer(const uint64_t id)
{
    if (!_loop)
    {
        lg(Warning, "loop is unllptr, can't call delayTimer");
        return false;
    }
    _loop->PushTask([this, id] { this->delayTimerTask(id); });
    return true;
}

bool TimeWheel::cancelTimer(const uint64_t id)
{
    if (!_loop)
    {
        lg(Warning, "loop is unllptr, can't call addTimer");
        return false;
    }
    _loop->PushTask([this, id] { this->cancelTimerTask(id); });
    return true;
}

/////////////////////////////////
// 当前类是为了将一个线程和一个时间循环绑定在一起，创建线程及创建eventLoop
class loopThread
{
private:
    eventLoop* _loop = nullptr;
    std::mutex _mtx;
    std::condition_variable _cond;
    std::thread _thread;
private:
    void threadEntry(size_t maxOutTime)
    {
        {
            std::unique_lock<std::mutex> guide(_mtx);
            _loop = new eventLoop(maxOutTime);
            _loop->init();
            _cond.notify_all();
        }
        _loop->start();
    }
public:
    loopThread(size_t maxTimeOut = defaultMaxTimeOut) : _thread(&loopThread::threadEntry, this, maxTimeOut) {}
    eventLoop* getLoop()
    {
        // 为了防止获取的时候loop还没有创建成功，需要先判断
        if (_loop == nullptr)
        {
            // 当loop还没有创建好的时候，不能直接获得直到被条件变量环唤醒
            std::unique_lock<std::mutex> guide(_mtx);
            _cond.wait(guide, [&] { return _loop != nullptr; });
        }
        return _loop;
    }
};

// 这里是将所有的eventLoop模块结合成loop池方便时间分配
// 采用RR轮转的方法分配连接
// 这里为了满足一些清凉级应用场景，允许使用者传入参数为0，此时主从reactor模型将会变成单reactor模型
class loopThreadPool
{
private:
    size_t _pos = 0;
    size_t _loopNum;
    eventLoop* _mainLoop;
    std::vector<loopThread*> _loops;
    std::vector<eventLoop*> _events;
    size_t _maxOutTime;
public:
    loopThreadPool(eventLoop* mainLoop, const size_t loopNum, const size_t maxOutTime = defaultMaxTimeOut) :
        _mainLoop(mainLoop), _loopNum(loopNum), _loops(loopNum), _maxOutTime(maxOutTime) {}
    ~loopThreadPool() { lg(Info, "loopThread pool is release"); }

public:
    void init()
    {
        for (auto& pthread : _loops)
        {
            pthread = new loopThread(_maxOutTime);
            _events.push_back(pthread->getLoop());
        }
    }
    // 获取一个用于分配的从reactor
    eventLoop* getLoop()
    {
        if (!_loopNum)
            return _mainLoop;
        else
        {
            auto ret = _events[_pos];
            _pos = (_pos + 1) % _loopNum;
            return ret;
        }
    }
};

/* 关于连接整体管理的一个封装类 */
enum class connectStatue
{
    Connecting,    // 连接完成，尚未初始化
    Connected,     // 连接就绪
    DisConnected,  // 连接已经关闭
    DisConnecting  // 连接关闭，但尚未完成善后工作
};

// 为什么有channel还要有connection？
// connection用于保存从客户端接收的未处理的数据并且保存处理完未发送的数据
// 并且channel模块负责的是接收处理数据的必须逻辑，用户可以再connection模块中自己添加可选功能以及应用层协议选择

class connection;
using ptrConnection = std::shared_ptr<connection>;
/*各种函数调用*/
using anyEventFunc = std::function<void(const ptrConnection&)>;
using protocolFunc = std::function<void(const ptrConnection&, Buffer&)>;
using connectedFunc = std::function<void(const ptrConnection&)>;
using closeConFunc = std::function<void(const ptrConnection&)>;
// 关于对连接的所有操作，为了防止线程安全问题，仍然都是在eventLoop模块中进行的
class connection : public std::enable_shared_from_this<connection>
{
private:
    uint64_t _id;                        // connection id, 外部设置， 和定时任务id绑定在一起
    tcpSocket _socket;                   // 对当前连接的接收和发送功能
    eventLoop* _loop;                    // 指向所处的事件循环
    channel _channel;                    // 对当前连接的各个事件管理
    connectStatue _stat;                 // 表示当前连接的所处阶段
    bool _enableInactiveFree = false;    // 标识当前连接是否开启了非活跃连接释放
    Buffer _inBuffer;                    // 输入缓冲区
    Buffer _outBuffer;                   // 输出缓冲区
    std::any _context;                   // 存储上下文
    size_t _outTime;                     // 定时时间
private:      /*设置回调函数用于各种事件的处理*/

    anyEventFunc _allEventCb;               // 任何事件触发之后调用的回调
    protocolFunc _protocolCb;               // 关于协议处理的回调
    connectedFunc _connectedCb;             // 连接完成之后调用的回调
    closeConFunc _closedCb;                  // 连接关闭之后调用的回调
    /*服务器关闭当前链接要调用的回调*/
    closeConFunc _svrCloseCb;

public:  /*回调函数的设置*/
    void setAnyEventCb(const anyEventFunc& cb) { _allEventCb = cb; }
    void setProtocolCb(const protocolFunc& cb) { _protocolCb = cb; }
    void setConnectedCb(const connectedFunc& cb) { _connectedCb = cb; }
    void setClosedCb(const closeConFunc& cb) { _closedCb = cb; }
    void setSvrConCloseCb(const closeConFunc& cb) { _svrCloseCb = cb; }

private:
    /*对channel模块的五个事件的处理回调*/
    void handleRead()       // 对当前连接读时间到来的处理
    {
        char buffer[65536];
        while (true)
        {
            // 以非阻塞方式进行读取
            ssize_t n = _socket.recv(buffer, sizeof buffer - 1, true);
            if (n == -1)
            {
                if (errno == EWOULDBLOCK) break;
                else if (errno == EINTR) continue;
                else
                {
                    lg(Warning, "read the link, fd: %d error, errno: %d, \"%s\"", errno, strerror(errno));
                    release();       // 如果读取出错了，那就直接关闭连接，不需要再继续维护连接了
                    return;
                }
            }
            if (n == 0)
            {
                // 对端关闭了连接, 此时需要直接释放连接
                release();
                return;
            }
            // 将读取结果放入缓冲区中
            buffer[n] = 0;
            // lg(Info, "connect id: %ld @ %s", _id, buffer);
            _inBuffer.write(buffer, static_cast<size_t>(n));
            if (_inBuffer.getReadAbleSize() > 0)
            {
                _protocolCb(shared_from_this(), _inBuffer);
                // 事件处理完成之后还应该要调用一下延时函数，防止处理时间过久触发了非活跃连接释放
                if (_enableInactiveFree) _loop->delayTimer(_id);
            }
        }
    }
    void handleWrite()
    {
        // 把输出缓冲区中的数据进行发送
        size_t sz = _outBuffer.getReadAbleSize();
        if (sz)  // 输出缓冲区有数据才进行发送
        {
            ssize_t n = _socket.send(_outBuffer.getReadPos(), sz, true);
            if (n < 0)
            {
                if (errno == EWOULDBLOCK || errno == EINTR) return;
                lg(Warning, "write to link, fd: %d error, errno: %d, \"%s\"", errno, strerror(errno));
                release();
                return;
            }
            // 发送完成之后，还需要将outBuffer中已经写入的数据删除
            _outBuffer.readerIdxGo(n);
        }
        // 如果已经没有数据继续发送了，那就要关闭写事件监控，并且如果此时已经是处于待关闭状态，那就直接调用关闭连接
        if (_outBuffer.getReadAbleSize() == 0)
        {
            // 1. 取消写时间监控
            _channel.delMonitorWrite();
            // 2. 如果已经处于待关闭状态，直接进行释放连接操作
            if (_stat == connectStatue::DisConnecting)
                release();
        }
    }
    void handleClose()
    {
        // 既然对端已经关闭了连接了，那就不用再处理数据了，直接关闭即可
        // 1. 对于连接中的任务，关闭事件只需要打个日志就可以了
        lg(Debug, "this connection: %ld get a close event", _id);
        // 接下来在handleChannel中就会将EPOLLIN事件描述符进行标记
        // 在进行读事件处理的时候就会进行连接释放操作
    }
    void handleError()
    {
        lg(Warning, "this connection: %ld get a error event", _id);
        // 接下来在handleChannel中就会将EPOLLIN事件描述符进行标记
        // 在进行读事件处理的时候就会进行连接释放操作
    }
    void handleAllEvent()
    {
        // lg(Debug, "this connection: %ld get a event", _id);
        // 1. 调用用户设置的任意事件接收回调函数
        if (_allEventCb) _allEventCb(shared_from_this());
        // 只有设置了非活跃连接释放才需要延长时间
        if (_enableInactiveFree) _loop->delayTimer(_id);
    }

public: /*构造，析构函数*/
    // 当构造函数被调用时，就表示连接建立完成了
    connection(eventLoop* loop, uint64_t id, int fd = -1) :_enableInactiveFree(false), _socket(fd), _loop(loop), _channel(_loop, fd), _stat(connectStatue::Connecting), _id(id)
    {
        // 为当前link设置一系列回调函数
        _channel.setAllCb([this] { this->handleAllEvent(); });
        _channel.setCloseCb([this] { this->handleClose(); });
        _channel.setErrCb([this] { this->handleError(); });
        _channel.setReadCb([this] { this->handleRead(); });
        _channel.setWriteCb([this] { this->handleWrite();});
    }
    ~connection() { lg(Info, "connection close, id: %ld", _id); }

private: /*在loop中要执行的内部操作*/
    void sendInLoop(const Buffer buf)                      // 发送数据操作
    {
        if (isDisConnected())
        {
            lg(Warning, "this connect already closed, can't send mesg");
            return;
        }
        // 1. 将数据写入缓冲区中
        _outBuffer.write(buf);
        // lg(Debug, "now read size: %ld", _outBuffer.getReadAbleSize());
        // 2. 启用当前连接的写事件监控
        if (!_channel.isMonitorWrite())
            _channel.setMonitorWrite();
    }
    void closeInLoop()                                // 表示当服务器端主动关闭连接的时候，需要先将待发送的数据全部发送，然后关闭连接
    {
        if (isDisConnected())
        {
            lg(Warning, "this connect already closed, can't send mesg");
            return;
        }
        // 1. 将当前连接状态设置为待关闭
        _stat = connectStatue::DisConnecting;
        // 2. 处理剩下的事件
        if (_inBuffer.getReadAbleSize())
            _protocolCb(shared_from_this(), _inBuffer);
        // 3. 启动写事件监控
        if (_outBuffer.getReadAbleSize() > 0)
        {
            if (!_channel.isMonitorWrite())
                _channel.setMonitorWrite();
        }
        else
            release();
        // 如果触发读事件之后发送没有数据写入，会直接对链接进行释放

    }
    void releaseInLoop()                              // 进行真正的连接释放操作
    {
        // 1. 移除对当前链接的事件监控
        _channel.revChannel();
        // 2. 关闭描述符
        _socket.close();
        // 3. 如果还有有关该connection的定时任务，需要取消
        if (_loop->hasTimer(_id))
            _loop->cancelTimer(_id);
        // 4. 将状态设置成关闭状态
        _stat = connectStatue::DisConnected;
        // 5. 调用用户设置的关闭连接函数 
        if (_closedCb) _closedCb(shared_from_this());
        // 6. 调用外部的释放连接函数
        if (_svrCloseCb) _svrCloseCb(shared_from_this());
    }
    void establishInLoop()                            // 连接真正的建立
    {
        // 进行连接完成的上一步应该是待连接
        assert(_stat == connectStatue::Connecting);
        // 打开读时间监控
        _channel.setMonitorRead();
        // 将状态设置成建立连接状态
        _stat = connectStatue::Connected;
        // 调用用户设置的连接成功回调
        if (_connectedCb) _connectedCb(shared_from_this());
    }
    void startInactiveFreeInLoop(size_t outTime)      // 打开非活跃连接释放功能
    {
        // 设置非活跃连接标记位为true
        _enableInactiveFree = true;
        // 如果存在，延迟时间即可， 如果不存在，添加定时任务
        if (_loop->hasTimer(_id))
            _loop->delayTimer(_id);
        else
            _loop->addTimer(_id, outTime, [this] { this->close(); });
    }
    void endInactiveFreeInLoop()        // 关闭非活跃连接释放功能
    {
        // 设置非活跃连接标记位为false
        if (!_loop->hasTimer(_id)) return;
        _loop->cancelTimer(_id);
    }

public:
    uint64_t id() { return _id; }
    int fd() { return _socket.fd(); }
    bool isConnected() { return _stat == connectStatue::Connected; }
    bool isDisConnected() { return _stat == connectStatue::DisConnected; }
    void send(const void* data, size_t len)         // 将数据写入到发送缓冲区中，并开启写监控
    {
        // 注意，这里一定要先用buffer将数据存储下来
        // 否则在调用pushTask之后如果没有立即执行，并且上层数据消失，就会导致错误的发生
        Buffer tmp;
        tmp.write(data, len);
        // printf("tmp mesg: %s\n", tmp.getReadPos());
        _loop->PushTask([this, tmp] { this->sendInLoop(tmp); });
    }
    void establish() { _loop->PushTask([this] { this->establishInLoop(); }); }                                                // 连接建立以后，进行的初始化操作
    void close() { _loop->PushTask([this] { this->closeInLoop(); }); }                                                        // 关闭连接, 进入connectStatus::DisConnecting状态, 处理完剩余事件之后进行release
    void release() { _loop->pushTaskToPoll([this] { this->releaseInLoop(); }); }                                                    // 释放连接， 进入conneectStatus::DisConnected状态
    void startInactiveFree(size_t outTime) { _loop->PushTask([this, outTime] { this->startInactiveFreeInLoop(outTime);}); }   // 启用非活跃连接释放功能
    void endInactiveFree() { _loop->PushTask([this] { this->endInactiveFreeInLoop(); }); }                                    // 关闭非活跃连接释放功能
    //  更新协议
    void changeProtocol(const std::any& context, const protocolFunc& protocl, const anyEventFunc& ae, const closeConFunc& close, const connectedFunc& con)
    {
        // 更新协议如果放在任务池中，就会导致如果协议还没有更新的时候如果又出现了一个新的事件，会按照旧的协议处理，这是不允许的，所以一定要在eventLoop模块中执行
        _loop->assertInLoop();
        _context = context;
        _protocolCb = protocl;
        _allEventCb = ae;
        _closedCb = close;
        _connectedCb = con;
    }
    /*对上下文的处理相关接口*/
    std::any& getContext() { return _context; }
    void setContext(const std::any& context) { _context = context; }
};

// 监听套接字
class acceptor
{
private:
    tcpSocket _sock;
    channel _channel;
    eventLoop* _loop;
    using newConnectFunc = std::function<void(int)>;
    newConnectFunc _newConnectCb;
public:
    // 设置新连接回调函数
    void setNewConnectFunc(const newConnectFunc& cb) { _newConnectCb = cb; }
private:
    int creatListenFd(const uint16_t port)
    {
        if (!_sock.createServer(port))
        {
            lg(Fatal, "create listen sock error");
            abort();
        }
        return _sock.fd();
    }

public:
    acceptor(eventLoop* loop, uint16_t port) :_sock(creatListenFd(port)), _channel(loop, _sock.fd()), _loop(loop)
    {
        _channel.setReadCb([this] {this->handleRead(); });
    }
    ~acceptor() = default;
private:
    void handleRead()
    {
        std::string srcIp;
        uint16_t srcPort;
        int fd = _sock.accept(&srcIp, &srcPort);
        if (fd < 0)
        {
            lg(Warning, "socket accept error");
            return;
        }
        lg(Info, "get a new link, srcIp: %s, srcPort: %hu", srcIp.c_str(), srcPort);
        if (_newConnectCb) _newConnectCb(fd);
    }
public:
    // 开始启动listen，监听读时间， 这里不能直接在构造函数启动监听是因为要先等待使用者设置好回调函数
    void start()
    {
        lg(Info, "acceptor start listen!");
        _channel.setMonitorRead();
    }
};


// loopThreadPool:init
// eventLoop, acceptor:start
class tcpServer
{
private:
    uint16_t _port;
    eventLoop _mainLoop;
    acceptor _acceptor;
    loopThreadPool _pool;
    size_t _loopMaxTimeOut;
    bool _InactiveLinkFree = false;
    std::unordered_map<uint64_t, ptrConnection> _connections;
    size_t _conOutTime;
    size_t _conId = 0;
    anyEventFunc _allEventCb;               // 任何事件触发之后调用的回调
    protocolFunc _protocolCb;               // 关于协议处理的回调
    connectedFunc _connectedCb;             // 连接完成之后调用的回调
    closeConFunc _closedCb;                  // 连接关闭之后调用的回调
    /*外部服务器关闭连接要调用的回调*/
    closeConFunc _svrCloseCb;
public:
    tcpServer(const uint16_t port, const size_t threadNum, const size_t loopMaxOutTime = defaultMaxTimeOut)
        : _port(port), _loopMaxTimeOut(loopMaxOutTime), _mainLoop(loopMaxOutTime),
        _acceptor(&_mainLoop, port), _pool(&_mainLoop, threadNum, loopMaxOutTime) {}
    ~tcpServer() = default;

public: /*设置各种回调函数*/
    void setAnyEventCb(const anyEventFunc& cb) { _allEventCb = cb; }
    void setProtocolCb(const protocolFunc& cb) { _protocolCb = cb; }
    void setConnectedCb(const connectedFunc& cb) { _connectedCb = cb; }
    void setClosedCb(const closeConFunc& cb) { _closedCb = cb; }
    void setSvrConCloseCb(const closeConFunc& cb) { _svrCloseCb = cb; }

private:
    void addId() { _conId++; if (_conId == SIZE_MAX) _conId = 0; }
    /*为新建立的连接创建connection*/
    void handleaccept(int fd)
    {
        addId();
        // 创建新连接
        ptrConnection newCon = std::make_shared<connection>(_pool.getLoop(), _conId, fd);
        // printf("new connection, %d", _conId);
        // 设置各种回调
        newCon->setAnyEventCb(_allEventCb);
        newCon->setClosedCb(_closedCb);
        newCon->setConnectedCb(_connectedCb);
        newCon->setProtocolCb(_protocolCb);
        newCon->setSvrConCloseCb([this](const ptrConnection& ptr) { this->removeCon(ptr);});
        // 打开非活跃连接释放
        if (_InactiveLinkFree) newCon->startInactiveFree(_conOutTime);
        // 连接初始化完成，启动连接
        newCon->establish();
        // 插入到管理connection模块中
        while (_connections.count(_conId))
        {
            lg(Warning, "this id: %d already exists!");
            addId();
        }
        _connections[_conId] = newCon;
    }
private:
    void removeConInLoop(const ptrConnection& ptr)
    {
        auto id = ptr->id();
        if (!_connections.count(id))
        {
            lg(Warning, "connections hash map can't find the con, fd: %ld", id);
            return;
        }
        _connections.erase(id);
        // printf("close connection, %d\n", id);
        lg(Info, "connection, id: %d realease from svr success!", id);
    }
    void removeCon(const ptrConnection& ptr) { _mainLoop.PushTask([this, ptr] { this->removeConInLoop(ptr);}); }
    void addTimerInLoop(const functor& fun, size_t delay)
    {
        addId();
        _mainLoop.addTimer(_conId, delay, fun);
    }
public: /*向外提供的接口*/
    void init()
    {
        // 防止服务器向一个关闭的连接发送数据导致出错
        signal(SIGPIPE, SIG_IGN);
        _mainLoop.init();
        _pool.init();
        _acceptor.setNewConnectFunc([this](const int fd) { this->handleaccept(fd);});
        _acceptor.start();
    }
    void setInactiveFree(size_t conOutTime) { _InactiveLinkFree = true; _conOutTime = conOutTime; }
    void endInactiveFree() { _InactiveLinkFree = false; }
    void start() { _mainLoop.start(); }
    /*提供用户一个参加定时任务的接口*/
    void addTimer(const functor& fun, const size_t delay) { _mainLoop.PushTask([this, fun, delay] { this->addTimerInLoop(fun, delay); }); }

};
